<template>
  <div>
    <el-form>
      <el-form-item label="SPU名称">
        <el-input
          placeholder="请你输入SPU名称"
          v-model="spuParams.spuName"
        ></el-input>
      </el-form-item>
      <el-form-item label="SPU品牌">
        <el-select placeholder="请你选择品牌" v-model="spuParams.tmId">
          <el-option
            :label="trademark.tmName"
            :value="trademark.id"
            v-for="(trademark, index) in trademarkArr"
            :key="trademark.id"
          ></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="SPU描述">
        <el-input
          type="textarea"
          placeholder="请你输入SPU描述"
          v-model="spuParams.description"
        ></el-input>
      </el-form-item>
      <el-form-item label="SPU图片">
        <!-- 照片墙组件:
        v-model:file-list,照片墙展示图片的属性[需要的数据]
        照片钱需要展示数据:数组 + 对象[name|url]
        action:照片钱上传新的图片，服务器地址
        list-type:何种形式展示图片(3种)
        on-preview:预览
     -->
        <el-upload
          v-model:file-list="imgArr"
          action="/app-dev/admin/product/fileUpload"
          list-type="picture-card"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
        >
          <el-icon><HelpFilled /></el-icon>
        </el-upload>
        <el-dialog v-model="dialogVisible">
          <img
            w-full
            :src="dialogImageUrl"
            alt="Preview Image"
            style="
              width: 200px;
              height: 200px;
              margin: 10px auto;
              display: block;
            "
          />
        </el-dialog>
      </el-form-item>
      <el-form-item label="销售属性">
        <el-select
          :placeholder="
            unselectSaleAttr.length > 0
              ? `您还有${unselectSaleAttr.length}未选择`
              : '无'
          "
          v-model="unsaleAttrNameAndId"
        >
          <!--未选择销售属性-->
          <el-option
            :label="sale.name"
            :value="`${sale.id}:${sale.name}`"
            v-for="(sale, index) in unselectSaleAttr"
            :key="sale.id"
          ></el-option>
        </el-select>
        <el-button
          style="margin-left: 10px"
          type="primary"
          size="default"
          :icon="Plus"
          :disabled="unsaleAttrNameAndId ? false : true"
          @click="addSaleAttr"
          >添加销售属性</el-button
        >
        <el-table border style="margin: 10px 0px" :data="saleAttr">
          <el-table-column
            label="序号"
            type="index"
            align="center"
            width="80"
          ></el-table-column>
          <el-table-column
            label="属性名"
            width="100"
            prop="saleAttrName"
          ></el-table-column>
          <el-table-column label="属性值">
            <!--row:即为已有的销售属性对象-->
            <template #="{ row, $index }">
              <!--每一个销售属性的属性值用tag展示-->
              <el-tag
                style="margin: 5px 5px"
                @close="closehandler(row, index)"
                :type="item.id % 2 == 0 ? 'success' : 'warning'"
                v-for="(item, index) in row.spuSaleAttrValueList"
                :key="item.id"
                closable
                >{{ item.saleAttrValueName }}</el-tag
              >
              <!--编辑模式与查看模式切换-->
              <el-button
                v-if="!row.show"
                @click="toEdit(row, $index)"
                type="primary"
                size="small"
                :icon="Plus"
              ></el-button>
              <el-input
                v-model="row.saleAttrValueName"
                :ref="(el) => (inputArr[$index] = el)"
                @blur="toLook(row)"
                v-else
                placeholder="请你输入属性值"
                size="small"
                style="width: 100px; display: inline-block"
              ></el-input>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="100">
            <template #="{ row, $index }">
              <el-button
                type="danger"
                size="small"
                :icon="Delete"
                @click="saleAttr.splice($index, 1)"
              ></el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-button
          type="primary"
          size="default"
          :disabled="saleAttr.length > 0 ? false : true"
          @click="save"
          >保存</el-button
        >
        <el-button size="default" @click="cancel">取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, nextTick } from "vue";
//引入请求的函数
import {
  reqAllTradeMark,
  reqImgList,
  reqSpuHasSaleAttr,
  reqAllSaleAttr,
  reqAddOrUpdateSpu,
} from "../../../api/product/spu/index";
import { Plus, HelpFilled, Delete } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import type { UploadProps, UploadUserFile } from "element-plus";

//存储已有SPU:品牌数据
let trademarkArr = ref([]);
//存储已有SPU的照片墙的数据
let imgArr = ref([]);
//存储已有的销售属性
let saleAttr = ref([]);
//存储全部销售属性
let allSaleAttr = ref([]);
//准备参数:接受已有SPU,模板展示
let spuParams = ref<any>({
  category3Id: "", //三级分类的ID,代表这个已有SPU归属于哪一个三级分类
  tmId: "", //收集品牌的ID
  spuName: "", //SPU名字
  description: "", //spu的描述
  spuImageList: [
    //携带照片墙的数据
  ],
  spuSaleAttrList: [
    //销售属性与属性值
  ],
});
//定义响应式数据:收集未选择的销售属性ID与名字
let unsaleAttrNameAndId = ref("");
//存储对话框里面图片路径
const dialogImageUrl = ref("");
//控制预览对话框显示与隐藏
const dialogVisible = ref(false);

//用于存储编辑模式与查看模式切换的时候,表单元素
let inputArr = ref([]);

//收集销售属性值的数据
//照片组件:删除按钮的回调
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  //uploadFile:用户删除的图片对象
  //uploadFiles:删除以后剩余的全部图片
};
//预览的钩子
const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  //uploadFile:点击预览按钮底下图片的数据
  dialogImageUrl.value = uploadFile.url;
  //展示对话框
  dialogVisible.value = true;
};

//取消按钮的回调
const cancel = () => {
  $emit("changeScene",{newScene:0,flag:'update'});
};

//子组件的方法:拼凑出一个完整已有SPU
//spu + 底部四个数据[四个数组]->完整的已有的SPU
const initHasSpuData = async (spu) => {
  //存储已有的SPU
  Object.assign(spuParams.value, spu);
  //获取全部品牌的数据
  let result = await reqAllTradeMark();
  //获取已有SPU照片墙的数据
  let result1 = await reqImgList(spu.id);
  //获取已有SPU:已经拥有销售属性与属性值
  let result2 = await reqSpuHasSaleAttr(spu.id);
  //获取全部销售属性
  let result3 = await reqAllSaleAttr();
  //存储数据
  trademarkArr.value = result;
  //由于照片墙的数据格式:里面对象K:name|url,服务器返回照片墙数据格式并非人家需要，处理一下
  let imgResult = result1.map((item) => {
    return {
      name: item.imgName,
      url: item.imgUrl,
    };
  });
  imgArr.value = imgResult;

  saleAttr.value = result2;
  allSaleAttr.value = result3;
};

//计算出还没有被选择销售属性
let unselectSaleAttr = computed(() => {
  //外层数组:全部销售属性  颜色、版本、尺码
  //内存数组:颜色
  let result = allSaleAttr.value.filter((item) => {
    return saleAttr.value.every((item1) => {
      return item.name != item1.saleAttrName;
    });
  });
  return result;
});

//添加销售属性按钮的回调
const addSaleAttr = () => {
  //准备参数
  let [baseSaleAttrId, saleAttrName] = unsaleAttrNameAndId.value.split(":");
  //准备一个新增的销售属性对象,将来发请求携带给服务器
  let newSaleAttr = {
    baseSaleAttrId, //新增销售属性的ID
    saleAttrName, //新增销售属性的名字
    spuSaleAttrValueList: [], //新增销售属性值的数组
  };

  //添加新的销售属性
  saleAttr.value.push(newSaleAttr);
  //收集到未选择销售属性的数据清空
  unsaleAttrNameAndId.value = "";
};

//添加销售属性值按钮的回调->变为编辑模式
const toEdit = (row, index) => {
  //给销售属性对象动态添加show标记:控制编辑模式与查看模式的切换
  row.show = true;
  //收集新增的属性值
  row.saleAttrValueName = "";
  //响应式数据show发生变化,模板进行再次更新,获取更新后的DOM
  nextTick(() => {
    inputArr.value[index].focus();
  });
};

//表单元素失却焦点事件->变为查看模式
const toLook = (row) => {
  //准备属性值对象
  let saleAttrValueObj = {
    baseSaleAttrId: row.baseSaleAttrId, //销售属性的ID
    saleAttrValueName: row.saleAttrValueName,
  };

  //非法情况判断:属性值的名字不能为空
  if (saleAttrValueObj.saleAttrValueName.trim() == "") {
    ElMessage({
      message: "属性值不能为空",
      type: "error",
    });
    //属性值为空后面语句不在执行
    return;
  }

  //非法情况:新增的属性值是否在数组当中出现
  let repeat = row.spuSaleAttrValueList.find((item) => {
    return saleAttrValueObj.saleAttrValueName === item.saleAttrValueName;
  });

  if (repeat) {
    ElMessage({
      message: "属性值不能重复",
      type: "error",
    });
    return;
  }
  //销售属性的属性值数组新增一个属性值
  row.spuSaleAttrValueList.push(saleAttrValueObj);
  //清空当前收集到属性值
  row.saleAttrValueName = "";
  //变为查看模式
  row.show = false;
};

//tag组件叉子的点击事件回调\
//row:即为当前销售属性对象  index 销售属性值的下角标
const closehandler = (row, index) => {
  //删除选中销售属性值
  row.spuSaleAttrValueList.splice(index, 1);
};

//保存按钮的方法
const save = async () => {
  // console.log(imgArr.value);
  //整理修改已有SPU需要携带参数
  //照片墙的数据
  let imgParams = imgArr.value.map((item) => {
    return {
      imgName: item.name,
      imgUrl: (item.response && item.response.data) || item.url,
    };
  });
  spuParams.value.spuImageList = imgParams;
  //销售属性的数据
  spuParams.value.spuSaleAttrList = saleAttr.value;
  try {
    //更新或添加SPU的请求
    let result = await reqAddOrUpdateSpu(spuParams.value);
    //文字提示
    ElMessage({
      message: spuParams.value.id ? "修改SPU成功" : "添加SPU成功",
      type: "success",
    });
    //通知父组件切换场景
    $emit("changeScene",{newScene:0,flag:spuParams.value.id?'update':'add'});
  } catch (error) {
    ElMessage({
      message: spuParams.value.id ? "修改SPU失败" : "添加SPU失败",
      type: "error",
    });
  }
};

//添加SPU初始化数据的方法
const initAddSpu = async (c3Id: string | number) => {
  //清空收集的数据+收集到三级分类的ID
  Object.assign(spuParams.value, {
    category3Id: c3Id, //三级分类的ID,代表这个已有SPU归属于哪一个三级分类
    tmId: "", //收集品牌的ID
    spuName: "", //SPU名字
    description: "", //spu的描述
    spuImageList: [
      //携带照片墙的数据
    ],
    spuSaleAttrList: [
      //销售属性与属性值
    ],
  });
  //清空照片墙的数据
  imgArr.value = [];
  //清空销售属性的数据
  saleAttr.value = [];
  spuParams.value.id='';
  
  //获取全部品牌的数据
  let result = await reqAllTradeMark();
  //获取全部销售属性
  let result1 = await reqAllSaleAttr();
  //存储全部品牌的数据
  trademarkArr.value = result;
  //存储全部销售属性
  allSaleAttr.value = result1;
};

//emit方法
let $emit = defineEmits(["changeScene"]);
//对外暴露方法:父亲可以使用此方法
defineExpose({
  initHasSpuData,
  initAddSpu,
});
</script>

<style scoped>
</style>